package proyectoia;

import IA.DistFS.Servers;
import aima.search.framework.GoalTest;
import aima.search.framework.HeuristicFunction;
import aima.search.framework.Search;
import aima.search.framework.SuccessorFunction;
import aima.search.informed.HillClimbingSearch;
import aima.search.informed.SimulatedAnnealingSearch;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.math3.stat.descriptive.SummaryStatistics;

public class StagedExperiment6 extends StagedExperiment {
    
    SimulatedAnnealingSearch searchSA;
    HillClimbingSearch searchHC;
    float similiratiy;

    public StagedExperiment6(int seed, int nIterations, 
            Integer steps, Integer stiter, Integer k, Double lambda) {
        super(seed, nIterations);
        numStages = 2;
        searchSA = new SimulatedAnnealingSearch(steps,stiter,k,lambda);
        searchHC = new  HillClimbingSearch();
        similiratiy = (float) 0.4;
    }

    @Override
    protected int getNumUsers() {
        return 200;
    }

    @Override
    protected int getNumRequests() {
        return 5;
    }

    @Override
    protected int getNumServers() {
        return 50;
    }

    @Override
    protected int getNumReplications() {
        return 5;
    }

    @Override
    protected DistFileSystemState getInitialSolution(DistFileSystemState state) {
        state.generateGreedySolution();
        return state;
    }

    @Override
    protected Search getSearch() {
        switch(currentStage) {
            case 2: 
                return searchHC;
            case 3: 
                return searchHC;
            case 0: 
                return searchSA;      
            case 1: 
                return searchSA;
        }
        return null;
    }

    @Override
    protected SuccessorFunction getSuccessor() {
        switch (currentStage) {
            case 2:
                return new DistFileSystemSuccessorFunction2b();
            case 3:
                return new DistFileSystemSuccessorFunction2b();
            case 0:
                return new DistFileSystemSuccessorFunctionSA1();
            case 1:
                return new DistFileSystemSuccessorFunctionSA1();
        }
        return null;
    }

    @Override
    protected GoalTest getGoalTest() {
        return new DistFileSystemGoalTest();
    }
    
    @Override
    protected Integer getSearchResult() {
        switch (currentStage) {
            case 2:
               return ACTIONS;
            case 3:
                return ACTIONS;
            case 0:
                return STATES;
            case 1:
                return STATES;
         }
        
        return null;
    }

    @Override
    protected HeuristicFunction getHeuristic() {
         switch (currentStage) {
            case 0:
                return new DistFileSystemHeuristicFunction1();
            case 1:
                return new DistFileSystemHeuristicFunction2(similiratiy);
            case 2:
                return new DistFileSystemHeuristicFunction1();
            case 3:
                return new DistFileSystemHeuristicFunction2(similiratiy);
         }
        
        return null;
    }
    
    protected void printDifTime(String filename) throws IOException, Exception {
        FileWriter outFile = new FileWriter("data/" + filename + "-diff-time.data");
        PrintWriter o = new PrintWriter(outFile);
        o.println("# Slowest server time");
        for (int s = 0; s < numStages; s++) {
            this.currentStage = s;
            o.println("# " + stageName(s));
            SummaryStatistics is = new SummaryStatistics();
            for (int i = 0; i < numIterations; i++) {
                is.addValue(initialStates[s].get(i).getSlowestServerTime());
            }
            System.out.println(stageName(s));
            //System.out.println("\tTemps servidor més lent inici " + (int) is.getMean() + " amb " + (int) is.getStandardDeviation() + " stdev per " + numIterations + " iteracions.");
            SummaryStatistics ss = new SummaryStatistics();
            SummaryStatistics rt = new SummaryStatistics();
            for (int i = 0; i < numIterations; i++) {
                DistFileSystemState firstState = new DistFileSystemState(initialStates[s].get(i));
                DistFileSystemState lastState = getLastState(firstState, searchAgents[s].get(i));
                Integer firstTime = firstState.getTotalServerTime();
                Integer lastTime = lastState.getTotalServerTime();
                ss.addValue(firstTime-lastTime);
                rt.addValue(runTimes[s].get(i));
                o.print(firstTime-lastTime + "\t");
                
                System.out.println("temps incial "+firstTime);
                System.out.println("temps final  "+lastTime);
            }
            o.println();
            System.out.println("\tGuany de temps " + (int) ss.getMean() + " amb " + (int) ss.getStandardDeviation() + " stdev per " + numIterations + " iteracions. " + (int) rt.getMean() + "ms amb " + (int) rt.getStandardDeviation() + " stdev en executar-se.");
        }
        o.close();
    }
    
    public static void main(String[] args) throws Servers.WrongParametersException {
        StagedExperiment6 se = new StagedExperiment6(123, 10, 20000, 50, 125, 0.00000001);
        try {
            se.initialitze();
            se.execute();
            se.printSlowestServerTime("experiment-6");
            se.printSlowestServerGainTime("experiment-6");
            se.printDifTime("experiment-6");
            
        } catch (Exception e) {
            Logger.getLogger(DistFileSystem.class.getName()).log(Level.SEVERE, null, e);
        }
    }
}
